#include "Socket.hpp"
using namespace socket_ns;
#include "InetAddr.hpp"
#include <memory>
#include <functional>
#include <pthread.h>


using io_service_t = std::function<void(sock_sptr, InetAddr)>;

class TcpServer;
struct ThreadData
{
    sock_sptr _sptr;
    InetAddr _addr;
    TcpServer* _self;
    ThreadData(sock_sptr sptr, InetAddr addr, TcpServer* ts)
        :_sptr(sptr), _addr(addr), _self(ts)
    {}
};

class TcpServer
{
public:
    TcpServer(uint16_t port, io_service_t service)
        :_port(port),
         _addr(_port, "0"),
         _listenSock(std::make_unique<TcpSocket>()),
         _service(service)
    {
        _listenSock->BuildListenSocket(_addr);
    }
    static void* HandlerSock(void* args)
    {
        ThreadData* td = reinterpret_cast<ThreadData*>(args);
        td->_self->_service(td->_sptr, td->_addr);
        delete td;
        return nullptr;
    }
    void Loop()
    {
        while(true)
        {
            InetAddr clientaddr;
            sock_sptr sptr = _listenSock->Accepter(clientaddr);

            pthread_t tid;
            ThreadData* td = new ThreadData(sptr, clientaddr, this);
            pthread_create(&tid, nullptr, HandlerSock, td);
        }
    }
private:
    uint16_t _port;
    InetAddr _addr;
    std::unique_ptr<Socket> _listenSock;

    io_service_t _service;
};